import fs from 'fs-extra';
import path from 'path';
import { ComponentParser } from '../parser/parser';
import { VueComponent } from '../core/types';

/**
 * 生成HTML文档
 * @param scanPaths 要扫描的组件路径
 * @param outputPath 输出路径
 * @param vueVersion Vue版本
 * @param customParser 自定义解析器实例（可选）
 */
export async function generateHtml(
  scanPaths: string[],
  outputPath: string,
  vueVersion: string = 'auto',
  customParser?: ComponentParser
): Promise<void> {
  // 使用提供的解析器或创建新解析器
  const parser = customParser || new ComponentParser(scanPaths, vueVersion);
  
  // 如果使用的是新创建的解析器，需要解析组件
  if (!customParser) {
    await parser.parseComponents();
  }
  
  const components = parser.getComponentList();

  // 确保输出目录存在
  await fs.ensureDir(outputPath);
  
  // 确保静态资源目录存在
  const assetsDir = path.join(outputPath, 'assets');
  await fs.ensureDir(assetsDir);
  
  // 复制CSS和JS
  await createStylesheet(assetsDir);
  await createScript(assetsDir);

  // 生成索引文件
  await generateIndexFile(components, outputPath);

  // 为每个组件生成文档文件
  for (const component of components) {
    await generateComponentFile(component, outputPath);
  }
}

/**
 * 生成索引文件
 * @param components 组件列表
 * @param outputPath 输出路径
 */
async function generateIndexFile(components: VueComponent[], outputPath: string): Promise<void> {
  const sortedComponents = [...components].sort((a, b) => a.name.localeCompare(b.name));
  
  let componentList = '';
  for (const component of sortedComponents) {
    componentList += `
      <div class="component-item">
        <a href="${component.name}.html" class="component-link">
          <h3>${component.name}</h3>
          <p>${component.description || '无描述'}</p>
        </a>
      </div>
    `;
  }

  const html = `
<!DOCTYPE html>
<html lang="zh">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Vue组件文档</title>
  <link rel="stylesheet" href="assets/style.css">
</head>
<body>
  <div class="container">
    <header>
      <h1>Vue组件文档</h1>
      <p>生成时间: ${new Date().toLocaleString()}</p>
    </header>
    
    <main>
      <div class="component-grid">
        ${componentList}
      </div>
    </main>
    
    <footer>
      <p>由VueLens自动生成</p>
    </footer>
  </div>
  <script src="assets/script.js"></script>
</body>
</html>
  `;

  await fs.writeFile(path.join(outputPath, 'index.html'), html, 'utf-8');
}

/**
 * 生成组件文档文件
 * @param component 组件信息
 * @param outputPath 输出路径
 */
async function generateComponentFile(component: VueComponent, outputPath: string): Promise<void> {
  // 属性表格
  let propsTable = '';
  if (component.props.length > 0) {
    propsTable = `
      <table>
        <thead>
          <tr>
            <th>名称</th>
            <th>类型</th>
            <th>默认值</th>
            <th>是否必填</th>
            <th>描述</th>
          </tr>
        </thead>
        <tbody>
          ${component.props.map(prop => {
            // 添加可能的值的显示
            const valuesStr = prop.values && prop.values.length > 0 
              ? `<div class="possible-values">可选值: ${prop.values.join(', ')}</div>` 
              : '';
            
            return `
              <tr>
                <td>${prop.name}</td>
                <td><code>${prop.type}</code></td>
                <td>${prop.defaultValue ? `${prop.defaultValue}` : '-'}</td>
                <td>${prop.required ? '是' : '否'}</td>
                <td>${prop.description || '-'}${valuesStr}</td>
              </tr>
            `;
          }).join('')}
        </tbody>
      </table>
    `;
  } else {
    propsTable = '<p>该组件没有定义属性。</p>';
  }

  // 事件部分
  let eventsSection = '';
  if (component.events.length > 0) {
    eventsSection = component.events.map(event => {
      let argsTable = '';
      if (event.arguments.length > 0) {
        argsTable = `
          <h4>参数:</h4>
          <table>
            <thead>
              <tr>
                <th>名称</th>
                <th>类型</th>
                <th>描述</th>
              </tr>
            </thead>
            <tbody>
              ${event.arguments.map(arg => `
                <tr>
                  <td>${arg.name}</td>
                  <td><code>${arg.type}</code></td>
                  <td>${arg.description || '-'}</td>
                </tr>
              `).join('')}
            </tbody>
          </table>
        `;
      }

      return `
        <div class="event-item">
          <h3>${event.name}</h3>
          <p>${event.description || '无描述'}</p>
          ${argsTable}
        </div>
      `;
    }).join('');
  } else {
    eventsSection = '<p>该组件没有定义事件。</p>';
  }

  // 插槽部分
  let slotsSection = '';
  if (component.slots.length > 0) {
    slotsSection = component.slots.map(slot => {
      let bindingsTable = '';
      if (slot.bindings.length > 0) {
        bindingsTable = `
          <h4>作用域:</h4>
          <table>
            <thead>
              <tr>
                <th>名称</th>
                <th>类型</th>
                <th>描述</th>
              </tr>
            </thead>
            <tbody>
              ${slot.bindings.map(binding => `
                <tr>
                  <td>${binding.name}</td>
                  <td><code>${binding.type}</code></td>
                  <td>${binding.description || '-'}</td>
                </tr>
              `).join('')}
            </tbody>
          </table>
        `;
      }

      return `
        <div class="slot-item">
          <h3>${slot.name}</h3>
          <p>${slot.description || '无描述'}</p>
          ${bindingsTable}
        </div>
      `;
    }).join('');
  } else {
    slotsSection = '<p>该组件没有定义插槽。</p>';
  }

  // 方法部分
  let methodsSection = '';
  if (component.methods.length > 0) {
    methodsSection = component.methods.map(method => {
      let paramsTable = '';
      if (method.params.length > 0) {
        paramsTable = `
          <h4>参数:</h4>
          <table>
            <thead>
              <tr>
                <th>名称</th>
                <th>类型</th>
                <th>默认值</th>
                <th>描述</th>
              </tr>
            </thead>
            <tbody>
              ${method.params.map(param => `
                <tr>
                  <td>${param.name}</td>
                  <td><code>${param.type}</code></td>
                  <td>${param.defaultValue ? `${param.defaultValue}` : '-'}</td>
                  <td>${param.description || '-'}</td>
                </tr>
              `).join('')}
            </tbody>
          </table>
        `;
      }

      const returnType = method.returns?.type || 'void';
      const returnDesc = method.returns?.description || '-';

      return `
        <div class="method-item">
          <h3>${method.name}</h3>
          <p>${method.description || '无描述'}</p>
          
          <h4>签名:</h4>
          <pre><code>${method.name}(${method.params.map(p => p.name).join(', ')}): ${returnType}</code></pre>
          
          ${paramsTable}
          
          <h4>返回值:</h4>
          <p><code>${returnType}</code> - ${returnDesc}</p>
        </div>
      `;
    }).join('');
  } else {
    methodsSection = '<p>该组件没有定义公共方法。</p>';
  }

  // 示例部分
  let exampleSection = '';
  if (component.example) {
    exampleSection = `
      <div class="section">
        <h2>示例</h2>
        <pre><code class="language-vue">${escapeHtml(component.example)}</code></pre>
      </div>
    `;
  }

  const html = `
<!DOCTYPE html>
<html lang="zh">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>${component.name} - Vue组件文档</title>
  <link rel="stylesheet" href="assets/style.css">
</head>
<body>
  <div class="container">
    <header>
      <h1>${component.name}</h1>
      <p class="back-link"><a href="index.html">返回首页</a></p>
    </header>
    
    <main>
      <div class="section">
        <h2>基本信息</h2>
        <div class="info-grid">
          <div class="info-item">
            <strong>描述</strong>
            <span>${component.description || '无描述'}</span>
          </div>
          <div class="info-item">
            <strong>文件路径</strong>
            <code>${component.filePath}</code>
          </div>
          <div class="info-item">
            <strong>Vue版本</strong>
            <span>${component.vueVersion}</span>
          </div>
          <div class="info-item">
            <strong>创建时间</strong>
            <span>${new Date(component.createdAt).toLocaleString()}</span>
          </div>
          <div class="info-item">
            <strong>更新时间</strong>
            <span>${new Date(component.updatedAt).toLocaleString()}</span>
          </div>
        </div>
      </div>
      
      <div class="section">
        <h2>属性</h2>
        ${propsTable}
      </div>
      
      <div class="section">
        <h2>事件</h2>
        ${eventsSection}
      </div>
      
      <div class="section">
        <h2>插槽</h2>
        ${slotsSection}
      </div>
      
      <div class="section">
        <h2>方法</h2>
        ${methodsSection}
      </div>
      
      ${exampleSection}
    </main>
    
    <footer>
      <p>由VueLens自动生成</p>
    </footer>
  </div>
  <script src="assets/script.js"></script>
</body>
</html>
  `;

  await fs.writeFile(path.join(outputPath, `${component.name}.html`), html, 'utf-8');
}

/**
 * 创建样式表
 * @param assetsDir 资源目录
 */
async function createStylesheet(assetsDir: string): Promise<void> {
  const css = `
:root {
  --color-primary: #41b883;
  --color-secondary: #35495e;
  --color-text: #2c3e50;
  --color-text-light: #666;
  --color-border: #eaecef;
  --color-bg: #fff;
  --color-bg-secondary: #f8f8f8;
  --color-bg-code: #f6f6f6;
  --font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
  --font-family-code: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', monospace;
}

* {
  box-sizing: border-box;
}

body {
  font-family: var(--font-family);
  color: var(--color-text);
  margin: 0;
  padding: 0;
  line-height: 1.6;
}

.container {
  max-width: 1200px;
  margin: 0 auto;
  padding: 0 20px;
}

header {
  padding: 40px 0;
  text-align: center;
  border-bottom: 1px solid var(--color-border);
  margin-bottom: 40px;
}

h1 {
  color: var(--color-primary);
  margin: 0 0 10px;
}

header p {
  color: var(--color-text-light);
  margin: 0;
}

main {
  margin-bottom: 60px;
}

.component-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
  gap: 20px;
}

.component-item {
  padding: 20px;
  border-radius: 8px;
  border: 1px solid var(--color-border);
  transition: transform 0.2s, box-shadow 0.2s;
}

.component-item:hover {
  transform: translateY(-5px);
  box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1);
}

.component-link {
  text-decoration: none;
  color: inherit;
}

.component-link h3 {
  color: var(--color-primary);
  margin: 0 0 10px;
}

.component-link p {
  color: var(--color-text-light);
  margin: 0;
}

.section {
  margin-bottom: 40px;
}

.section h2 {
  color: var(--color-secondary);
  padding-bottom: 10px;
  border-bottom: 1px solid var(--color-border);
}

.info-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
  gap: 20px;
}

.info-item {
  display: flex;
  flex-direction: column;
}

.info-item strong {
  color: var(--color-secondary);
  margin-bottom: 5px;
}

table {
  width: 100%;
  border-collapse: collapse;
  margin: 20px 0;
}

table th, table td {
  padding: 12px 15px;
  text-align: left;
  border-bottom: 1px solid var(--color-border);
}

table th {
  background-color: var(--color-bg-secondary);
  font-weight: 600;
}

code {
  font-family: var(--font-family-code);
  background-color: var(--color-bg-code);
  padding: 2px 5px;
  border-radius: 3px;
  font-size: 0.9em;
}

pre {
  background-color: var(--color-bg-code);
  padding: 20px;
  border-radius: 8px;
  overflow-x: auto;
}

pre code {
  background-color: transparent;
  padding: 0;
}

.back-link {
  margin-top: 20px;
}

.back-link a {
  color: var(--color-primary);
  text-decoration: none;
}

.back-link a:hover {
  text-decoration: underline;
}

.event-item, .slot-item, .method-item {
  margin-bottom: 30px;
  padding: 20px;
  border-radius: 8px;
  background-color: var(--color-bg-secondary);
}

.event-item h3, .slot-item h3, .method-item h3 {
  color: var(--color-primary);
  margin-top: 0;
}

footer {
  text-align: center;
  padding: 20px 0;
  border-top: 1px solid var(--color-border);
  color: var(--color-text-light);
}

@media (max-width: 768px) {
  .info-grid {
    grid-template-columns: 1fr;
  }
  
  .component-grid {
    grid-template-columns: 1fr;
  }
}
  `;

  await fs.writeFile(path.join(assetsDir, 'style.css'), css, 'utf-8');
}

/**
 * 创建脚本文件
 * @param assetsDir 资源目录
 */
async function createScript(assetsDir: string): Promise<void> {
  const js = `
document.addEventListener('DOMContentLoaded', function() {
  // 为代码块添加高亮逻辑
  const codeBlocks = document.querySelectorAll('pre code');
  if (codeBlocks.length > 0) {
    // 简单的语法高亮
    codeBlocks.forEach(function(block) {
      highlight(block);
    });
  }
});

function highlight(block) {
  // 简单的语法高亮，可以替换为完整的语法高亮库
  const html = block.innerHTML;
  
  // 高亮关键字
  const keywords = [
    'const', 'let', 'var', 'function', 'return', 'if', 'else', 'for', 'while',
    'import', 'export', 'from', 'default', 'class', 'extends', 'new', 'this',
    'props', 'computed', 'methods', 'data', 'watch', 'components', 'setup', 'ref',
    'reactive', 'defineComponent', 'onMounted', 'onUnmounted'
  ];
  
  // 替换字符串和注释
  let highlightedHtml = html;
  
  // 替换字符串
  highlightedHtml = highlightedHtml.replace(/(["'])(.*?)\\1/g, '<span class="string">$&</span>');
  
  // 替换注释
  highlightedHtml = highlightedHtml.replace(/(\/\/.*)/g, '<span class="comment">$1</span>');
  
  // 替换关键字
  keywords.forEach(function(keyword) {
    const regex = new RegExp('\\\\b' + keyword + '\\\\b', 'g');
    highlightedHtml = highlightedHtml.replace(regex, '<span class="keyword">$&</span>');
  });
  
  block.innerHTML = highlightedHtml;
  
  // 添加高亮样式
  const style = document.createElement('style');
  style.textContent = \`
    code .string { color: #c41a16; }
    code .comment { color: #007400; }
    code .keyword { color: #0000ff; }
  \`;
  document.head.appendChild(style);
}
  `;

  await fs.writeFile(path.join(assetsDir, 'script.js'), js, 'utf-8');
}

/**
 * 转义HTML字符
 * @param html HTML字符串
 */
function escapeHtml(html: string): string {
  return html
    .replace(/&/g, '&amp;')
    .replace(/</g, '&lt;')
    .replace(/>/g, '&gt;')
    .replace(/"/g, '&quot;')
    .replace(/'/g, '&#039;');
} 